home *** CD-ROM | disk | FTP | other *** search
- #define STRICT
-
- // Includes standard Windows
- #include <windows.h>
- #include <windowsx.h>
- #include <time.h>
- #include <stdlib.h>
- #include <malloc.h>
- #include <memory.h>
- #include <stdio.h>
-
- // Includes D3D
- #define D3D_OVERLOADS
- #include <ddraw.h>
- #include <d3d.h>
- #include <d3dx.h>
-
- // Includes utilitaires D3D
- #include "d3dmath.h"
- #include "d3dutil.h"
- #include "D3DEnum.h"
-
- // Ids Resources
- #include "resource.h"
-
- // Constantes
- #include "const.h"
-
- // Types
- #include "types.h"
-
- // Variables globales projet
- #include "vars.h"
-
- // Prototypes fonctions autres modules
- #include "proto.h"
-
- // Macros
- #include "macros.h"
-
- // Variables statiques au module
- static BOOL bTracking = FALSE; // Poursuite curseur en cours o/n (WM_LBUTTONDOWN / WM_MOUSEMOVE)
- static WPARAM wModifier; // Mémorisé sur le LBUTTONDOWN : SHIFT / CTRL / ...
- static HBRUSH hbrDkBlueSk, hbrLtBlueSk; // Brosses de remplissage
- static HPEN hpenWhite, hpenGrey, hpenCyan, hpenYellow, hpenPink, hpenDkBlueSk, hpenRed; // Crayons
- static HFONT hFont;
-
-
- void vAddTextOutline(void)
- {
- #define XDC_HEADER 0
- #define XDC_CURVE 1
-
- GLYPHMETRICS sGlyphMetrics; // Récupérer infos de kerning du caractère courant
- MAT2 sMatrix; // Matrice identité (pourrait servir à faire tourner les caractères)
- WinThings * psWinProps // Pour récuperer un HDC avec font
- = (WinThings *) GetWindowLong(hWndFace, 0);
- CHOOSEFONT cf; // structure common dialog box
- static LOGFONT lf; // structure logical font
- static DWORD rgbCurrent; // current text color
- HFONT hfont, hfontPrev = NULL;
- float fFontScale = 1.f;
-
- // Initialize CHOOSEFONT
- ZeroMemory(&cf, sizeof(CHOOSEFONT));
- cf.lStructSize = sizeof (CHOOSEFONT);
- cf.hwndOwner = NULL;
- cf.lpLogFont = &lf;
- cf.rgbColors = rgbCurrent;
- cf.Flags = CF_BOTH | CF_TTONLY | CF_NOSCRIPTSEL | CF_INITTOLOGFONTSTRUCT;
- strcpy(lf.lfFaceName, "Arial");
-
- if (ChooseFont(&cf)==TRUE)
- {
- hfont = CreateFontIndirect(cf.lpLogFont);
- hfontPrev = (HFONT) SelectObject(psWinProps ->hdcDBuf, hfont);
- fFontScale = cf.iPointSize / 40.f;
- }
-
- // Saisir la chaîne
- if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_STRING), NULL, bStringDlgProc, 0))
- return;
-
- // Régler la matrice sur l'identité (pour ne pas faire tourner les caractères)
- sMatrix.eM11.value = sMatrix.eM22.value = 1;
- sMatrix.eM12.value = sMatrix.eM21.value =
- sMatrix.eM11.fract = sMatrix.eM22.fract = sMatrix.eM12.fract = sMatrix.eM21.fract = 0;
-
- // Pour chaque caractère de la chaîne
- for (char *pChar = cString ; *pChar ; pChar++)
- {
- TTPOLYGONHEADER *pPolyHeader;
- TTPOLYCURVE *pPolyCurve;
- DWORD iBufSize;
- BOOL bState = XDC_HEADER;
- POINTFX *pPoints;
- BYTE *pFullBuffer, *pBlock, *pCurve;
- int iVert0, iVert1, iVert2;
- float fValue, fKmin = 100000.f, fKmax = -100000.f;
- D3DVECTOR dVec = Cursor1;
-
- // Suppression des accents
- if (strchr("àâä", *pChar)) *pChar = 'a';
- if (strchr("éèêë", *pChar)) *pChar = 'e';
- if (strchr("ïî", *pChar)) *pChar = 'i';
- if (strchr("ôö", *pChar)) *pChar = 'o';
- if (strchr("ûü", *pChar)) *pChar = 'u';
- if (strchr("ÿ", *pChar)) *pChar = 'y';
-
- // Si le caractère est un espace, on fait seulement avancer le curseur
- if (*pChar == ' ')
- {
- switch(lWActive)
- {
- case XDC_WID_TOP : // X et Z
- case XDC_WID_FACE : // X et Y
- Cursor1.x += fFontScale * (sGlyphMetrics.gmBlackBoxX / 2.f);
- break;
-
- case XDC_WID_SIDE : // Z et Y
- Cursor1.z += fFontScale * (sGlyphMetrics.gmBlackBoxX / 2.f);
- break;
- }
- continue;
- }
-
- // Récupérer la taille du buffer de courbes définissant le caractère courant
- iBufSize = GetGlyphOutline(psWinProps ->hdcDBuf, *pChar, GGO_NATIVE, &sGlyphMetrics, 0, NULL, &sMatrix);
-
- // Si l'outliner n'est pas capable de générer le buffer pour le caractère, au suivant.
- if (iBufSize == 0xFFFFFFFF) continue;
-
- // Allouer le buffer de courbes
- if (!(pBlock = pFullBuffer = (unsigned char *) malloc(iBufSize)))
- continue;
-
- // Récupérer le buffer de courbes
- GetGlyphOutline(psWinProps ->hdcDBuf, *pChar, GGO_NATIVE, &sGlyphMetrics, iBufSize, pFullBuffer, &sMatrix);
-
- // Pour chaque bloc en-tête / courbe(s)
- while (pBlock < pFullBuffer + iBufSize - 1)
- {
- switch(bState)
- {
- case XDC_HEADER: // Si on est sur un en-tête
- // Récupérer un pointeur sur le header
- pPolyHeader = (TTPOLYGONHEADER *) pBlock;
-
- // Créer le point de départ de l'enveloppe du caractère, et mémoriser son indice
- switch(lWActive)
- {
- case XDC_WID_TOP : // X et Z
- dVec.x = Cursor1.x + fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
- dVec.z = Cursor1.z + fFontScale * (pPolyHeader -> pfxStart.y.value + (float) (pPolyHeader -> pfxStart.y.fract) / 65536.f);
- break;
-
- case XDC_WID_FACE : // X et Y
- dVec.x = Cursor1.x + fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
- dVec.y = Cursor1.y + fFontScale * (pPolyHeader -> pfxStart.y.value + (float) (pPolyHeader -> pfxStart.y.fract) / 65536.f);
- break;
-
- case XDC_WID_SIDE : // Z et Y
- dVec.z = Cursor1.z + fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
- dVec.y = Cursor1.y + fFontScale * (pPolyHeader -> pfxStart.y.value + (float) (pPolyHeader -> pfxStart.y.fract) / 65536.f);
- break;
- }
- iVert0 = iVert1 = iMakeVertex(dVec, XDC_ALLOWSAME);
- Vertices[iVert0].bSelected = TRUE;
-
- // Décaler le pointeur de bloc sur le bloc courant (qui est une courbe)
- pBlock += sizeof(TTPOLYGONHEADER);
- bState = XDC_CURVE;
-
- // Special SG Kludge : ??? la taille indiquée pour le buffer est apparemment 4 x nb_headers plus grosse que la réalité...
- iBufSize -= 4;
- break;
-
- case XDC_CURVE: // Si on est sur une courbe
- // Récupérer un pointeur sur la première courbe du bloc
- pCurve = pBlock;
-
- // Décaler le pointeur de bloc sur le bloc courant (qui est une courbe ou un header)
- pBlock += ((pPolyHeader -> cb) - sizeof(TTPOLYGONHEADER));
-
- // Pour chaque courbe du bloc
- do
- {
- // Récupérer un pointeur sur la structure courbe
- pPolyCurve = (TTPOLYCURVE *) pCurve;
-
- // Calculer la taille de la courbe (pour ensuite passer à la suivante dansle bloc)
- int iSize = pPolyCurve -> cpfx * sizeof(pPolyCurve -> apfx) + sizeof(pPolyCurve -> cpfx) + sizeof(pPolyCurve -> wType);
-
- // Récupérer un pointeur sur le tableau de points de la courbe
- pPoints = &(pPolyCurve -> apfx[0]);
-
- // Si la courbe est d'un type connu
- if ( pPolyCurve -> wType == TT_PRIM_LINE
- || pPolyCurve -> wType == TT_PRIM_QSPLINE
- || pPolyCurve -> wType == TT_PRIM_CSPLINE)
- // Pour chaque point de la courbe
- for (int iPoint = 0 ; iPoint < pPolyCurve -> cpfx ; iPoint++)
- {
- // Dessiner le point et tracer une arête avec le précédent
- switch(lWActive)
- {
- case XDC_WID_TOP : // X et Z
- dVec.x = Cursor1.x + fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
- dVec.z = Cursor1.z + fFontScale * (pPoints[iPoint].y.value + (float) (pPoints[iPoint].y.fract) / 65536.f);
- break;
-
- case XDC_WID_FACE : // X et Y
- dVec.x = Cursor1.x + fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
- dVec.y = Cursor1.y + fFontScale * (pPoints[iPoint].y.value + (float) (pPoints[iPoint].y.fract) / 65536.f);
- break;
-
- case XDC_WID_SIDE : // Z et Y
- dVec.z = Cursor1.z + fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
- dVec.y = Cursor1.y + fFontScale * (pPoints[iPoint].y.value + (float) (pPoints[iPoint].y.fract) / 65536.f);
- break;
- }
- iVert2 = iMakeVertex(dVec, XDC_ALLOWSAME);
- iMakeEdge(iVert2, iVert1);
-
- // Shifter le précédent
- iVert1 = iVert2;
-
- // Ajuster les mini / maxi du kerning pour ce caractère
- fValue = fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
- if (fKmin > fValue) fKmin = fValue;
- if (fKmax < fValue) fKmax = fValue;
-
- fValue = fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
- if (fKmin > fValue) fKmin = fValue;
- if (fKmax < fValue) fKmax = fValue;
- }
-
- // Passer à la courbe suivante dans le bloc
- pCurve += iSize;
-
- } while (pCurve < pBlock && pCurve < pFullBuffer + iBufSize);
-
- // Refermer la courbe si elle ne l'est pas encore
- //if (pPolyCurve -> wType == TT_PRIM_LINE)
- if (-1 == iFindEdge(iVert2, iVert0))
- iMakeEdge(iVert2, iVert0);
-
- // Le prochain bloc est un header
- bState = XDC_HEADER;
- break;
- }
- }
-
- // Libérer le buffer de courbes
- free(pFullBuffer);
-
- // Avancer le curseur
- switch(lWActive)
- {
- case XDC_WID_TOP : // X et Z
- case XDC_WID_FACE : // X et Y
- Cursor1.x += 1.15f * (fKmax - fKmin);
- break;
-
- case XDC_WID_SIDE : // Z et Y
- Cursor1.z += 1.15f * (fKmax - fKmin);
- break;
- }
- }
-
- // Remettre la fonte par défaut du DC si on l'a changée
- if (hfontPrev)
- {
- SelectObject(psWinProps ->hdcDBuf, hfontPrev);
-
- // Libérer la fonte créée
- DeleteFont(hfont);
- }
-
- }
-